package com.example.cd5160866.urlapp.utils;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class BitmapUtil {
	/**
	 * 按正方形裁切图片
	 */
	public static Bitmap ImageCrop(Bitmap bitmap) {
		if (bitmap == null)
			return null;
		int w = bitmap.getWidth(); // 得到图片的宽，高

		int h = bitmap.getHeight();

		int wh = w > h ? h : w;// 裁切后所取的正方形区域边长

		int retX = w > h ? (w - h) / 2 : 0;// 基于原图，取正方形左上角x坐标

		int retY = w > h ? 0 : (h - w) / 2;

		// 下面这句是关键

		return Bitmap.createBitmap(bitmap, retX, retY, wh, wh, null, false);

	}

	/**
	 * 超过1.5*maxWidth 或者1.5*maxHeight时才会压缩
	 * 
	 * @param maxWidth
	 *            最大期望宽度
	 * @param maxHeight
	 *            最大期望高度
	 * @param fileName
	 *            文件名
	 * @return
	 */
	public static Bitmap getBitmap(int maxWidth, int maxHeight, String fileName) {
		Options options = getBitmapOptions(fileName);
		int widthSize = options.outWidth / maxWidth;
		int heightSize = options.outHeight / maxHeight;
		if (options.outWidth % maxWidth > maxWidth / 2) {
			widthSize = widthSize + 1;
		}
		if (options.outHeight % maxHeight > maxHeight / 2) {
			heightSize = heightSize + 1;
		}
		if (widthSize > heightSize) {
			options.inSampleSize = widthSize;
		} else {
			options.inSampleSize = heightSize;
		}
		return BitmapFactory.decodeFile(fileName, options);
	}

	public static Options getBitmapOptions(String fileName) {
		Options options = new Options();
		options.inJustDecodeBounds = true;
		BitmapFactory.decodeFile(fileName, options);
		options.inJustDecodeBounds = false;
		return options;
	}

	public static byte[] Bitmap2Bytes(Bitmap bm) {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		bm.compress(Bitmap.CompressFormat.JPEG, 60, baos);
		return baos.toByteArray();
	}

	public static void Bitmap2File(File file, Bitmap bm) {
		try {
			if (!file.exists())
				file.createNewFile();
			FileOutputStream fos = new FileOutputStream(file);
			fos.write(Bitmap2Bytes(bm));
			fos.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void parseToFile(File file, byte[] image, int mMaxWidth,
                                   int mMaxHeight) {
		Bitmap2File(file, parseToBitmap(image, mMaxWidth, mMaxHeight,true));
	}

	public static Bitmap parseToBitmap(byte[] image, int mMaxWidth,
                                       int mMaxHeight, boolean shouldScale) {
		BitmapFactory.Options decodeOptions = new BitmapFactory.Options();
		Bitmap bitmap = null;
		if (mMaxWidth == 0 && mMaxHeight == 0) {
			// decodeOptions.inPreferredConfig = mDecodeConfig;
			bitmap = BitmapFactory.decodeByteArray(image, 0, image.length,
					decodeOptions);
		} else {
			// If we have to resize this image, first get the natural bounds.
			decodeOptions.inJustDecodeBounds = true;
			BitmapFactory
					.decodeByteArray(image, 0, image.length, decodeOptions);
			int actualWidth = decodeOptions.outWidth;
			int actualHeight = decodeOptions.outHeight;

			// Then compute the dimensions we would ideally like to decode to.
			int desiredWidth = getResizedDimension(mMaxWidth, mMaxHeight,
					actualWidth, actualHeight);
			int desiredHeight = getResizedDimension(mMaxHeight, mMaxWidth,
					actualHeight, actualWidth);

			// Decode to the nearest power of two scaling factor.
			decodeOptions.inJustDecodeBounds = false;
			// TODO(ficus): Do we need this or is it okay since API 8 doesn't
			// support it?
			// decodeOptions.inPreferQualityOverSpeed =
			// PREFER_QUALITY_OVER_SPEED;
			decodeOptions.inSampleSize = findBestSampleSize(actualWidth,
					actualHeight, desiredWidth, desiredHeight);
			Bitmap tempBitmap = BitmapFactory.decodeByteArray(image, 0,
					image.length, decodeOptions);

			// If necessary, scale down to the maximal acceptable size.
			if (shouldScale&&tempBitmap != null
					&& (tempBitmap.getWidth() > desiredWidth || tempBitmap
							.getHeight() > desiredHeight)) {
					bitmap = Bitmap.createScaledBitmap(tempBitmap,
							desiredWidth, desiredHeight,true);
				tempBitmap.recycle();
			} else {
				bitmap = tempBitmap;
			}
		}
		return bitmap;
	}

	/**
	 * Scales one side of a rectangle to fit aspect ratio.
	 * 
	 * @param maxPrimary
	 *            Maximum size of the primary dimension (i.e. width for max
	 *            width), or zero to maintain aspect ratio with secondary
	 *            dimension
	 * @param maxSecondary
	 *            Maximum size of the secondary dimension, or zero to maintain
	 *            aspect ratio with primary dimension
	 * @param actualPrimary
	 *            Actual size of the primary dimension
	 * @param actualSecondary
	 *            Actual size of the secondary dimension
	 */
	private static int getResizedDimension(int maxPrimary, int maxSecondary,
			int actualPrimary, int actualSecondary) {
		// If no dominant value at all, just return the actual.
		if (maxPrimary == 0 && maxSecondary == 0) {
			return actualPrimary;
		}

		// If primary is unspecified, scale primary to match secondary's scaling
		// ratio.
		if (maxPrimary == 0) {
			double ratio = (double) maxSecondary / (double) actualSecondary;
			return (int) (actualPrimary * ratio);
		}

		if (maxSecondary == 0) {
			return maxPrimary;
		}

		double ratio = (double) actualSecondary / (double) actualPrimary;
		int resized = maxPrimary;
		if (resized * ratio > maxSecondary) {
			resized = (int) (maxSecondary / ratio);
		}
		return resized;
	}

	/**
	 * Returns the largest power-of-two divisor for use in downscaling a bitmap
	 * that will not result in the scaling past the desired dimensions.
	 * 
	 * @param actualWidth
	 *            Actual width of the bitmap
	 * @param actualHeight
	 *            Actual height of the bitmap
	 * @param desiredWidth
	 *            Desired width of the bitmap
	 * @param desiredHeight
	 *            Desired height of the bitmap
	 */
	private static int findBestSampleSize(int actualWidth, int actualHeight,
			int desiredWidth, int desiredHeight) {
		double wr = (double) actualWidth / desiredWidth;
		double hr = (double) actualHeight / desiredHeight;
		double ratio = Math.min(wr, hr);
		float n = 1.0f;
		while ((n * 2) <= ratio) {
			n *= 2;
		}

		return (int) n;
	}
}
